library(shiny)
library(dplyr)
library(tidyr)
library(ggplot2)
library(readr)
library(maps)
library(usmap)
library(gridExtra)
library(biscale)
library(cowplot)
library(sf)
library(shinythemes)
# ------------------------
# import data
# ------------------------
TX_counties <-read.csv("CData/texas0.csv")
Children_TX <-read.csv("CData/Children_TX.csv")
Adopt_Need <-read.csv("CData/Adopt_Need.csv")
Homes <-read.csv("CData/Homes.csv")
Removals <-read.csv("CData/Removals.csv")
Placements<-read.csv("CData/Placements.csv")
map_data <- read.csv("CData/Shiny_map_data.csv")
# Plotting Functions
create_homes_removals_plot <- function(map_data, year) {
color_map = c("#da4f58","#eda8a9","#e8e7e6",
"#a44c55","#b09ca5","#a4d5e1",
"#5a3f49","#5b7d8f","#43aac0")
x_text = "More Removals ->"
y_text = "More Homes ->"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# -----------------------------------------
# The breaks:
x_brk_points = c(3, 5) # removals
y_brk_points = c(6, 11) # homes
# -----------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
var2 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1,var2)
x = as.numeric(unlist(data[7]))
y = as.numeric(unlist(data[8]))
# create 3 buckets for variable 1
quantiles_x <- quantile(x,
probs = c(0,ecdf(x)(x_brk_points[1]),
ecdf(x)(x_brk_points[2]),1), na.rm = TRUE)
# create 3 buckets for variable 2
quantiles_y <- quantile(y,
probs = c(0,ecdf(y)(y_brk_points[1]),
ecdf(y)(y_brk_points[2]),1), na.rm = TRUE)
# create color scale that encodes two variables
bivariate_color_scale <- tibble(
"3 - 3" = color_map[1], # high X, high Y
"2 - 3" = color_map[2],
"1 - 3" = color_map[3], # low X, high Y
"3 - 2" = color_map[4],
"2 - 2" = color_map[5], # medium X, medium Y
"1 - 2" = color_map[6],
"3 - 1" = color_map[7], # high X, low Y
"2 - 1" = color_map[8],
"1 - 1" = color_map[9] # low X, low Y
) %>%
gather("group", "fill")
# cut into groups defined above and join fill
bar <- data %>%
mutate(
x_quantiles = cut(
x,
breaks = quantiles_x,
include.lowest = TRUE
),
y_quantiles = cut(
y,
breaks = quantiles_y,
include.lowest = TRUE
),
group = paste(
as.numeric(x_quantiles), "-",
as.numeric(y_quantiles)
)
) %>%
# we now join the actual hex values per "group"
# so each county has a hex value based on x and y
left_join(bivariate_color_scale, by = "group")
foo = bar %>% select(fips,fill)
colours = color_map
## ----------------------------------------------------------------
map <- plot_usmap(data = foo, values = "fill", include = c("TX"), color = "black", ) +
scale_fill_manual(
values = colours,
breaks = colours,
drop = FALSE, na.value = "white") + theme(legend.position = "none")
# CREATE THE LEGEND
group = c("3 - 3", "2 - 3", "1 - 3",
"3 - 2", "2 - 2", "1 - 2",
"3 - 1","2 - 1", "1 - 1")
fill = color_map
leg_data <- data.frame(group, fill)
# Create the legend
# separate the groups
leg_data %<>%
separate(group, into = c("x", "y"), sep = " - ") %>%
mutate(x = as.integer(x),
y = as.integer(y))
legend <- ggplot() +
geom_tile(
data = leg_data,
mapping = aes(
x = x,
y = y,
fill = color_map)
) +
scale_fill_identity() +
ylab(y_text) +
xlab(x_text) +
theme(axis.ticks.y = element_blank(),
axis.ticks.x = element_blank(),
axis.text.x = element_blank(), axis.text.y=element_blank(),
axis.title = element_text(size = 6)) +
coord_fixed() +
theme(plot.background = element_rect(color = "white", fill = "white"))
bivar_plot <- ggdraw() +
draw_plot(map, 0, 0, 1, 1) +
#draw_plot(legend, 0.05, 0.05, 0.3, 0.3) +
theme(plot.background = element_rect(color = "white", fill = "white"))
return(bivar_plot)
} # END OF FUNCTION # 1
create_homes_plot_simple <- function(map_data, year) {
legend_text = "FAD Homes per 100K residents"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#a9a9a9","#BE0D73","#F25E74","#FF8884","#34A1C7","#026178")
labels <- c()
brks <- c(0,10, 25, 50, 75, 100, 125)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") # was "bottom"
return(univar_plot)
} # END OF FUNCTION # 2
create_removals_plot_simple <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#a9a9a9","#eac259","#f39f62","#f67300","#e52835","#810301")
labels <- c()
brks <- c(0,5, 10, 15, 20, 30, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top")
return(univar_plot)
} # END OF FUNCTION # 3
extract_dataframe2 <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#a9a9a9","#eac259","#f39f62","#f67300","#e52835","#810301")
labels <- c()
brks <- c(0,5, 10, 15, 20, 30, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
return(data)
} # END OF FUNCTION # 3b
extract_priority_list2 <- function(map_data, year) {
color_map = c("#da4f58","#eda8a9","#e8e7e6",
"#a44c55","#b09ca5","#a4d5e1",
"#5a3f49","#5b7d8f","#43aac0")
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# -----------------------------------------
# The breaks:
x_brk_points = c(3, 5) # removals
y_brk_points = c(6, 11) # homes
# -----------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
var2 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1,var2)
x = as.numeric(unlist(data[7]))
y = as.numeric(unlist(data[8]))
# create 3 buckets for variable 1
quantiles_x <- quantile(x,
probs = c(0,ecdf(x)(x_brk_points[1]),
ecdf(x)(x_brk_points[2]),1), na.rm = TRUE)
# create 3 buckets for variable 2
quantiles_y <- quantile(y,
probs = c(0,ecdf(y)(y_brk_points[1]),
ecdf(y)(y_brk_points[2]),1), na.rm = TRUE)
# create color scale that encodes two variables
bivariate_color_scale <- tibble(
"3 - 3" = color_map[1], # high X, high Y
"2 - 3" = color_map[2],
"1 - 3" = color_map[3], # low X, high Y
"3 - 2" = color_map[4],
"2 - 2" = color_map[5], # medium X, medium Y
"1 - 2" = color_map[6],
"3 - 1" = color_map[7], # high X, low Y
"2 - 1" = color_map[8],
"1 - 1" = color_map[9] # low X, low Y
) %>%
gather("group", "fill")
# cut into groups defined above and join fill
bar <- data %>%
mutate(
x_quantiles = cut(
x,
breaks = quantiles_x,
include.lowest = TRUE
),
y_quantiles = cut(
y,
breaks = quantiles_y,
include.lowest = TRUE
),
group = paste(
as.numeric(x_quantiles), "-",
as.numeric(y_quantiles)
)
) %>%
# we now join the actual hex values per "group"
# so each county has a hex value based on x and y
left_join(bivariate_color_scale, by = "group")
foo = bar %>% select(fips,fill)
colours = color_map
# --------------------------------
the_list = sort(bar$County[bar$fips %in% (foo$fips[foo$fill=="#5a3f49"])])
return(the_list)
} # END OF FUNCTION # 7b
extract_dataframe <- function(map_data, year) {
color_map = c("#da4f58","#eda8a9","#e8e7e6",
"#a44c55","#b09ca5","#a4d5e1",
"#5a3f49","#5b7d8f","#43aac0")
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# -----------------------------------------
# The breaks:
x_brk_points = c(3, 5) # removals
y_brk_points = c(6, 11) # homes
# -----------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
var2 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1,var2)
x = as.numeric(unlist(data[7]))
y = as.numeric(unlist(data[8]))
# create 3 buckets for variable 1
quantiles_x <- quantile(x,
probs = c(0,ecdf(x)(x_brk_points[1]),
ecdf(x)(x_brk_points[2]),1), na.rm = TRUE)
# create 3 buckets for variable 2
quantiles_y <- quantile(y,
probs = c(0,ecdf(y)(y_brk_points[1]),
ecdf(y)(y_brk_points[2]),1), na.rm = TRUE)
# create color scale that encodes two variables
bivariate_color_scale <- tibble(
"3 - 3" = color_map[1], # high X, high Y
"2 - 3" = color_map[2],
"1 - 3" = color_map[3], # low X, high Y
"3 - 2" = color_map[4],
"2 - 2" = color_map[5], # medium X, medium Y
"1 - 2" = color_map[6],
"3 - 1" = color_map[7], # high X, low Y
"2 - 1" = color_map[8],
"1 - 1" = color_map[9] # low X, low Y
) %>%
gather("group", "fill")
# cut into groups defined above and join fill
bar <- data %>%
mutate(
x_quantiles = cut(
x,
breaks = quantiles_x,
include.lowest = TRUE
),
y_quantiles = cut(
y,
breaks = quantiles_y,
include.lowest = TRUE
),
group = paste(
as.numeric(x_quantiles), "-",
as.numeric(y_quantiles)
)
) %>%
# we now join the actual hex values per "group"
# so each county has a hex value based on x and y
left_join(bivariate_color_scale, by = "group")
foo = bar %>% select(fips,fill)
colours = color_map
# --------------------------------
return(bar)
} # END OF FUNCTION # 7b
map_data$empty_vec = rep(NA, 254)
plot_usmap(data = map_data, values = "empty_vec", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = "white", na.value="white") +
theme(plot.background = element_rect(color = "gray", fill = "gray"))

# ---------------
map_data <- map_data %>% separate(Region, c("DReg_Num", "Region"), "-")
map_data$DReg_Num <- as.numeric(as.character(map_data$DReg_Num))
legend_text = ""
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == 2021)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"DReg_Num", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$DReg_Num
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#4363d8","#aaffc3","#911eb4","#fabed4","#c50275","#42d4f4","#f58231","#dcbeff","#ffe119","#007c7c","#98D640","#a9a9a9")
labels <- c()
brks <- c(0,1, 2, 3, 4, 5, 6, 7, 8, 9,10,11)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = c("Lubbock","Abilene","Arlington","Tyler","Beaumont","Houston","Austin","San Antonio","Midland","El Paso","Edinburg"),
guide = guide_legend(
direction = "vertical",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 12,
byrow = F,
reverse = F,
label.position = "left"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="right")

NA
NA
Homes %>% group_by(Year) %>% summarise(Total = sum(Count))
Homes %>% group_by(Year, Type) %>% summarise(Total = sum(Count)) %>%
ggplot(aes(x = Year, y = Total, fill = Type)) +
geom_bar(stat = 'identity') +
ggtitle("") +
scale_x_continuous(name="Year", limits=c(2010.5, 2021.5), breaks = c(2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021)) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=30)) +
theme(axis.text.y = element_text(color="black", size=14, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
scale_fill_manual(name = "Home Type", values = c("#6091c2", "#21c5aa", "#000000"))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.

# 2011 bar chart
map_data_2011 <- map_data %>% filter(Year == "2011") %>% filter(Homes_Total_County==0)
sum(map_data_2011$Homes_Total_County==0)
[1] 53
map_data_2011 <- within(map_data_2011,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(map_data_2011, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "Region", x = "County Count")

# 2021 bar chart
map_data_2021 <- map_data%>% filter(Year == "2021") %>% filter(Homes_Total_County==0)
sum(map_data_2021$Homes_Total_County==0)
[1] 149
map_data_2021 <- within(map_data_2021,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(map_data_2021, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "DReg_Num", x = "County Count")

fig0 = create_homes_plot_simple(map_data, 2021)
fig0 + theme(legend.text=element_text(size=12))

# maps figure
fig1 = create_homes_plot_simple(map_data, 2011) +
theme(legend.position="none")
fig2 = create_homes_plot_simple(map_data, 2021) +
theme(legend.position="none")
grid.arrange(fig1+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.5)),
fig2+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.5)),
nrow = 1)

Removals %>% group_by(Year, Removal.Stage) %>% summarise(Total = sum(Removals)) %>% ggplot(aes(x = Year, y = Total, fill = Removal.Stage)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(color="black", size=12, angle=45)) +
theme(axis.text.y = element_text(color="black", size=12, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
ggtitle("") +
scale_x_continuous(name="Year", limits=c(2010.5, 2021.5), breaks = c(2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021)) +
scale_fill_manual(name = "Removal Stage", values = c("#058abd","#1c3152"))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.

# Trying to get percentages
Totals_byYear <- Removals %>% group_by(Year) %>% summarize(Total_Year = sum(Removals))
Totals_byStage_byYear <- Removals %>% group_by(Year, Removal.Stage) %>% summarize(Total_Stage = sum(Removals))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
x <- merge(Totals_byStage_byYear,Totals_byYear, by = "Year")
x <- mutate(x, Percent = (Total_Stage/Total_Year)*100)
x %>% ggplot(aes(x = Year, y = Percent, fill = Removal.Stage)) + geom_bar(stat = 'identity') + theme(axis.text.x = element_text(color="black", size=9, angle=45)) + ggtitle("") +
scale_x_continuous(name="Year", limits=c(2010.5, 2021.5), breaks = c(2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021)) +
theme(plot.background = element_rect(color = "#c9daf8", fill = "#c9daf8")) + scale_fill_manual(values = c("#058abd","#1c3152"))

Removals %>% group_by(Year) %>% summarise(Total = sum(Removals))
# 2021 bar chart
removals_data_2021 <- extract_dataframe2(map_data, 2021)
#"#eac259","#f39f62","#f67300"
removals_data_2021_high <- filter(removals_data_2021 , brks!="5") %>% select("Year", "County", "Region","brks")
removals_data_2021_high <- within(removals_data_2021_high,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(removals_data_2021_high, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "Region", x = "County Count")

# -------
library(ggtext)
my_caption = "<span style='color:#000000'>2011</span> <span style='color:#ececec'>2013 2015 2017 2019 2021</span>"
fig = create_removals_plot_simple(map_data, 2021)
fig + theme(legend.text=element_text(size=12))

##-----------------
fig3 = create_removals_plot_simple(map_data, 2011) +
theme(legend.position="none")
fig4 = create_removals_plot_simple(map_data, 2021) +
theme(legend.position="none")
grid.arrange(fig3+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.5)),
fig4+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.5)),
nrow = 1)

# Building the parts of the dataframe we will work with
mdata <- map_data %>% select("Year", "County",
"Homes_Total_County_per100K",
"Removals_Total_County_per1K")
mdata$Year<-as.factor(mdata$Year)
new1 <-mdata %>% group_by(County) %>% summarise(MeanHomes = mean(Homes_Total_County_per100K)) %>% select("MeanHomes")
new2 <-mdata %>% group_by(County) %>% summarise(MeanRemovals = mean(Removals_Total_County_per1K)) %>% select("MeanRemovals")
new1$MeanHomes[new1$MeanHomes==0] <- NA
new2$MeanRemovals[new2$MeanRemovals==0] <- NA
# Plot 1
layout(mat = matrix(c(1,2),2,1, byrow=TRUE), height = c(1,8))
par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(new1$MeanHomes, horizontal=TRUE , ylim=c(0,50), xaxt="n" , col=rgb(3/255,149/255,114/255,0.85) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(new1$MeanHomes, breaks=40 , col=rgb(0/255,0/255,124/255,0.85) , border=T , main="" , xlab="Average Number of Homes Per 100K Residents between 2011-2021", xlim=c(0,50))
# Plot 2
layout(mat = matrix(c(1,2),2,1, byrow=TRUE), height = c(1,8))
par(mar=c(0, 3.1, 1.1, 2.1))

boxplot(new2$MeanRemovals, horizontal=TRUE , ylim=c(0,15), xaxt="n" , col=rgb(3/255,149/255,114/255,0.85) , frame=F) + geom_hline(xintercept=10)
Warning: Ignoring unknown parameters: xintercept
NULL
par(mar=c(4, 3.1, 1.1, 2.1))
hist(new2$MeanRemovals, breaks=40 , col=rgb(0/255,0/255,124/255,0.85) , border=T , main="" , xlab="Average Number of Removals Per 1K Children between 2011-2021", xlim=c(0,15))

quantile(new1$MeanHomes,probs = 0.33333,na.rm = TRUE)
33.333%
5.469232
quantile(new1$MeanHomes,probs = 0.66667,na.rm = TRUE)
66.667%
10.55997
quantile(new2$MeanRemovals,probs = 0.33333,na.rm = TRUE)
33.333%
3.090681
quantile(new2$MeanRemovals,probs = 0.66667,na.rm = TRUE)
66.667%
4.908048
# Map Function with 3 Breaks
create_homes_plot_simple_3brks <- function(map_data, year) {
legend_text = "FAD Homes per 100K residents"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1)
#data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#43aabf","#a4d5e1","#969696")
labels <- c()
brks <- c(0,6,11,50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(65 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=12)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") + theme(text=element_text(size=12))
return(univar_plot)
} # END OF FUNCTION # 2 updated
create_removals_plot_simple_3brks <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
#data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#969696","#eda8a9","#cf3946")
labels <- c()
brks <- c(0,3, 5, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(65 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=12)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") + theme(text=element_text(size=12))
return(univar_plot)
} # END OF FUNCTION # 3 updated
fig_homes <- create_homes_plot_simple_3brks(map_data, 2021)
fig_removals <- create_removals_plot_simple_3brks(map_data, 2021)
grid.arrange(fig_homes+theme(plot.title = element_text(hjust = 0.5)),fig_removals+theme(plot.title = element_text(hjust = 0.5)),
nrow = 1)

create_homes_removals_plot(map_data, 2021)

the_list <- extract_priority_list2(map_data, 2021)
the_list
[1] "Bandera" "Baylor" "Bee" "Bosque"
[5] "Brooks" "Brown" "Burleson" "Burnet"
[9] "Callahan" "Clay" "Coleman" "Concho"
[13] "Cooke" "Cottle" "Culberson" "Dallam"
[17] "Dickens" "Donley" "Duval" "Eastland"
[21] "Falls" "Fayette" "Fisher" "Foard"
[25] "Frio" "Garza" "Goliad" "Gray"
[29] "Hall" "Hardeman" "Haskell" "Hopkins"
[33] "Hutchinson" "Jones" "Kinney" "Kleberg"
[37] "Knox" "La Salle" "Limestone" "Llano"
[41] "Lynn" "Madison" "Marion" "McCulloch"
[45] "Menard" "Milam" "Mills" "Montague"
[49] "Nolan" "Palo Pinto" "Pecos" "Potter"
[53] "Real" "Refugio" "Robertson" "San Saba"
[57] "Scurry" "Shackelford" "Somervell" "Stonewall"
[61] "Taylor" "Tom Green" "Washington" "Wichita"
[65] "Wilbarger" "Zapata" "Zavala"
bar <- extract_dataframe(map_data, 2021)
high_need_df <- filter(bar, fill=="#5a3f49") %>% select("Year", "County",
"Region")
table(high_need_df$Region)
Abilene Arlington Austin Edinburg El Paso
21 3 13 6 1
Lubbock Midland San Antonio Tyler
9 5 7 2
high_need_df <- within(high_need_df,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(high_need_df, aes(y = Region)) +
geom_bar(fill="#5a3f49") + theme(axis.text.x = element_text(color="black", size=12, angle=0)) + theme(axis.text.y = element_text(color="black", size=12, angle=0)) + labs(y = "Texas Region", x = "High-need County Count") + theme(text = element_text(size = 14))

NA
NA
library(ggtext)
my_caption = "<span style='color:#000000'>2011</span> <span style='color:#ececec'>2013 2015 2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2016)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

library(ggtext)
my_caption = "<span style='color:#ececec'>2011</span> <span style='color:#000000'>2013</span> <span style='color:#ececec'>2015 2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2013)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013</span> <span style='color:#000000'>2015</span> <span style='color:#ececec'>2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2015)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015</span> <span style='color:#000000'>2017</span> <span style='color:#ececec'>2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2017)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015 2017</span> <span style='color:#000000'>2019</span> <span style='color:#ececec'>2021</span>"
fig = create_homes_plot_simple(map_data, 2019)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015 2017 2019</span> <span style='color:#000000'>2021</span>"
fig = create_homes_plot_simple(map_data, 2021)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoc2hpbnkpCmxpYnJhcnkoZHBseXIpIApsaWJyYXJ5KHRpZHlyKSAKbGlicmFyeShnZ3Bsb3QyKSAKbGlicmFyeShyZWFkcikKbGlicmFyeShtYXBzKQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShiaXNjYWxlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoc2YpCmxpYnJhcnkoc2hpbnl0aGVtZXMpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIGltcG9ydCBkYXRhCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClRYX2NvdW50aWVzIDwtcmVhZC5jc3YoIkNEYXRhL3RleGFzMC5jc3YiKQpDaGlsZHJlbl9UWCA8LXJlYWQuY3N2KCJDRGF0YS9DaGlsZHJlbl9UWC5jc3YiKQpBZG9wdF9OZWVkIDwtcmVhZC5jc3YoIkNEYXRhL0Fkb3B0X05lZWQuY3N2IikKSG9tZXMgPC1yZWFkLmNzdigiQ0RhdGEvSG9tZXMuY3N2IikKUmVtb3ZhbHMgPC1yZWFkLmNzdigiQ0RhdGEvUmVtb3ZhbHMuY3N2IikKUGxhY2VtZW50czwtcmVhZC5jc3YoIkNEYXRhL1BsYWNlbWVudHMuY3N2IikKbWFwX2RhdGEgPC0gcmVhZC5jc3YoIkNEYXRhL1NoaW55X21hcF9kYXRhLmNzdiIpCmBgYAoKYGBge3J9CiMgUGxvdHRpbmcgRnVuY3Rpb25zCmNyZWF0ZV9ob21lc19yZW1vdmFsc19wbG90IDwtIGZ1bmN0aW9uKG1hcF9kYXRhLCB5ZWFyKSB7CiAgCiAgY29sb3JfbWFwID0gYygiI2RhNGY1OCIsIiNlZGE4YTkiLCIjZThlN2U2IiwKICAgICAgICAgICAgICAgICIjYTQ0YzU1IiwiI2IwOWNhNSIsIiNhNGQ1ZTEiLAogICAgICAgICAgICAgICAgIiM1YTNmNDkiLCIjNWI3ZDhmIiwiIzQzYWFjMCIpCiAgeF90ZXh0ID0gIk1vcmUgUmVtb3ZhbHMgLT4iCiAgeV90ZXh0ID0gIk1vcmUgSG9tZXMgLT4iICAKICAKICAjIEZpbHRlciBmb3IgQ2hvc2VuIFllYXIKICBtYXBfZGF0YV95ZWFyIDwtIGZpbHRlcihtYXBfZGF0YSwgWWVhciA9PSB5ZWFyKQogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjIFRoZSBicmVha3M6CiAgeF9icmtfcG9pbnRzID0gYygzLCA1KSAgICMgcmVtb3ZhbHMKICB5X2Jya19wb2ludHMgPSBjKDYsIDExKSAgIyBob21lcwogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAKICAjIEJ1aWxkaW5nIHRoZSBwYXJ0cyBvZiB0aGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoCiAgbWRhdGEgPC0gbWFwX2RhdGFfeWVhciAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiwgImZpcHMiLCAibG9uIiwgImxhdCIpCiAgCiAgIyBjcmVhdGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoIHRvIHBsb3QKICB2YXIxID0gbWFwX2RhdGFfeWVhciRSZW1vdmFsc19Ub3RhbF9Db3VudHlfcGVyMUsKICB2YXIyID0gbWFwX2RhdGFfeWVhciRIb21lc19Ub3RhbF9Db3VudHlfcGVyMTAwSwogIGRhdGEgPC0gY2JpbmQobWRhdGEsdmFyMSx2YXIyKSAgCiAgCiAgeCA9IGFzLm51bWVyaWModW5saXN0KGRhdGFbN10pKQogIHkgPSBhcy5udW1lcmljKHVubGlzdChkYXRhWzhdKSkKICAKICAjIGNyZWF0ZSAzIGJ1Y2tldHMgZm9yIHZhcmlhYmxlIDEKICBxdWFudGlsZXNfeCA8LSBxdWFudGlsZSh4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9icyA9IGMoMCxlY2RmKHgpKHhfYnJrX3BvaW50c1sxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjZGYoeCkoeF9icmtfcG9pbnRzWzJdKSwxKSwgbmEucm0gPSBUUlVFKQogICMgY3JlYXRlIDMgYnVja2V0cyBmb3IgdmFyaWFibGUgMgogIHF1YW50aWxlc195IDwtIHF1YW50aWxlKHksIAogICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gYygwLGVjZGYoeSkoeV9icmtfcG9pbnRzWzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNkZih5KSh5X2Jya19wb2ludHNbMl0pLDEpLCBuYS5ybSA9IFRSVUUpCiAgCiAgIyBjcmVhdGUgY29sb3Igc2NhbGUgdGhhdCBlbmNvZGVzIHR3byB2YXJpYWJsZXMKICBiaXZhcmlhdGVfY29sb3Jfc2NhbGUgPC0gdGliYmxlKAogICAgIjMgLSAzIiA9IGNvbG9yX21hcFsxXSwgIyBoaWdoIFgsIGhpZ2ggWQogICAgIjIgLSAzIiA9IGNvbG9yX21hcFsyXSwKICAgICIxIC0gMyIgPSBjb2xvcl9tYXBbM10sICMgbG93IFgsIGhpZ2ggWQogICAgIjMgLSAyIiA9IGNvbG9yX21hcFs0XSwKICAgICIyIC0gMiIgPSBjb2xvcl9tYXBbNV0sICMgbWVkaXVtIFgsIG1lZGl1bSBZCiAgICAiMSAtIDIiID0gY29sb3JfbWFwWzZdLAogICAgIjMgLSAxIiA9IGNvbG9yX21hcFs3XSwgIyBoaWdoIFgsIGxvdyBZCiAgICAiMiAtIDEiID0gY29sb3JfbWFwWzhdLAogICAgIjEgLSAxIiA9IGNvbG9yX21hcFs5XSAjIGxvdyBYLCBsb3cgWQogICkgJT4lCiAgICBnYXRoZXIoImdyb3VwIiwgImZpbGwiKQogIAogICMgY3V0IGludG8gZ3JvdXBzIGRlZmluZWQgYWJvdmUgYW5kIGpvaW4gZmlsbAogIGJhciA8LSBkYXRhICU+JQogICAgbXV0YXRlKAogICAgICB4X3F1YW50aWxlcyA9IGN1dCgKICAgICAgICB4LAogICAgICAgIGJyZWFrcyA9IHF1YW50aWxlc194LAogICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRQogICAgICApLAogICAgICB5X3F1YW50aWxlcyA9IGN1dCgKICAgICAgICB5LAogICAgICAgIGJyZWFrcyA9IHF1YW50aWxlc195LAogICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRQogICAgICApLAogICAgICBncm91cCA9IHBhc3RlKAogICAgICAgIGFzLm51bWVyaWMoeF9xdWFudGlsZXMpLCAiLSIsCiAgICAgICAgYXMubnVtZXJpYyh5X3F1YW50aWxlcykKICAgICAgKQogICAgKSAlPiUKICAgICMgd2Ugbm93IGpvaW4gdGhlIGFjdHVhbCBoZXggdmFsdWVzIHBlciAiZ3JvdXAiCiAgICAjIHNvIGVhY2ggY291bnR5IGhhcyBhIGhleCB2YWx1ZSBiYXNlZCBvbiB4IGFuZCB5CiAgICBsZWZ0X2pvaW4oYml2YXJpYXRlX2NvbG9yX3NjYWxlLCBieSA9ICJncm91cCIpCiAgCiAgZm9vID0gYmFyICU+JSBzZWxlY3QoZmlwcyxmaWxsKQogIGNvbG91cnMgPSBjb2xvcl9tYXAKICAKICAjIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgbWFwIDwtIHBsb3RfdXNtYXAoZGF0YSA9IGZvbywgdmFsdWVzID0gImZpbGwiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siLCApICsgIAogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIGJyZWFrcyA9IGNvbG91cnMsCiAgICAgIGRyb3AgPSBGQUxTRSwgbmEudmFsdWUgPSAid2hpdGUiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKICAKICAjIENSRUFURSBUSEUgTEVHRU5ECiAgZ3JvdXAgPSBjKCIzIC0gMyIsICIyIC0gMyIsICIxIC0gMyIsIAogICAgICAgICAgICAiMyAtIDIiLCAiMiAtIDIiLCAiMSAtIDIiLCAKICAgICAgICAgICAgIjMgLSAxIiwiMiAtIDEiLCAiMSAtIDEiKQogIGZpbGwgPSBjb2xvcl9tYXAKICBsZWdfZGF0YSA8LSBkYXRhLmZyYW1lKGdyb3VwLCBmaWxsKQogIAogICMgQ3JlYXRlIHRoZSBsZWdlbmQKICAjIHNlcGFyYXRlIHRoZSBncm91cHMKICBsZWdfZGF0YSAlPD4lCiAgICBzZXBhcmF0ZShncm91cCwgaW50byA9IGMoIngiLCAieSIpLCBzZXAgPSAiIC0gIikgJT4lCiAgICBtdXRhdGUoeCA9IGFzLmludGVnZXIoeCksCiAgICAgICAgICAgeSA9IGFzLmludGVnZXIoeSkpCiAgCiAgbGVnZW5kIDwtIGdncGxvdCgpICsKICAgIGdlb21fdGlsZSgKICAgICAgZGF0YSA9IGxlZ19kYXRhLAogICAgICBtYXBwaW5nID0gYWVzKAogICAgICAgIHggPSB4LAogICAgICAgIHkgPSB5LAogICAgICAgIGZpbGwgPSBjb2xvcl9tYXApCiAgICApICsKICAgIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArCiAgICB5bGFiKHlfdGV4dCkgKwogICAgeGxhYih4X3RleHQpICsKICAgIHRoZW1lKGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksIAogICAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNikpICsgCiAgICBjb29yZF9maXhlZCgpICsgCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpCiAgCiAgYml2YXJfcGxvdCA8LSBnZ2RyYXcoKSArCiAgICBkcmF3X3Bsb3QobWFwLCAwLCAwLCAxLCAxKSArCiAgICAjZHJhd19wbG90KGxlZ2VuZCwgMC4wNSwgMC4wNSwgMC4zLCAwLjMpICsgCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpCiAgCiAgcmV0dXJuKGJpdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAxCgpjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUgPC0gZnVuY3Rpb24obWFwX2RhdGEsIHllYXIpIHsKICAKICBsZWdlbmRfdGV4dCA9ICJGQUQgSG9tZXMgcGVyIDEwMEsgcmVzaWRlbnRzIgogIAogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkSG9tZXNfVG90YWxfQ291bnR5X3BlcjEwMEsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEpICAKICAKICBkYXRhJHZhcjFbZGF0YSR2YXIxPT0wXSA8LSBOQSAKICAKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIyBDb21wdXRlIHNjYWxlCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIGNvbG91cnMgPSBjKCIjYTlhOWE5IiwiI0JFMEQ3MyIsIiNGMjVFNzQiLCIjRkY4ODg0IiwiIzM0QTFDNyIsIiMwMjYxNzgiKQogIGxhYmVscyA8LSBjKCkKICBicmtzIDwtIGMoMCwxMCwgMjUsIDUwLCA3NSwgMTAwLCAxMjUpCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCgxMDAgLyBsZW5ndGgobGFiZWxzKSwgdW5pdHMgPSAibW0iKSwKICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICd0b3AnLAogICAgICAgIHRpdGxlLmhqdXN0ID0gMCwKICAgICAgICBsYWJlbC5oanVzdCA9IDEsCiAgICAgICAgbnJvdyA9IDEsCiAgICAgICAgYnlyb3cgPSBULAogICAgICAgIHJldmVyc2UgPSBGLAogICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpLCAKICAgICAgICBuYS50cmFuc2xhdGUgPSBGQUxTRSkgKyAKICAgIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKwogICAgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSArIAogICAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpICMgd2FzICJib3R0b20iCiAgCiAgcmV0dXJuKHVuaXZhcl9wbG90KQp9ICMgRU5EIE9GIEZVTkNUSU9OICMgMgoKY3JlYXRlX3JlbW92YWxzX3Bsb3Rfc2ltcGxlIDwtIGZ1bmN0aW9uKG1hcF9kYXRhLCB5ZWFyKSB7CiAgCiAgbGVnZW5kX3RleHQgPSAiUmVtb3ZhbHMgcGVyIDFLIGNoaWxkcmVuIgogIAogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxKSAgCiAgCiAgZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBjb2xvdXJzID0gYygiI2E5YTlhOSIsIiNlYWMyNTkiLCIjZjM5ZjYyIiwiI2Y2NzMwMCIsIiNlNTI4MzUiLCIjODEwMzAxIikKICBsYWJlbHMgPC0gYygpCiAgYnJrcyA8LSBjKDAsNSwgMTAsIDE1LCAyMCwgMzAsIDUwKQogIGZvcihpZHggaW4gMTpsZW5ndGgoYnJrcykpewogICAgbGFiZWxzIDwtIGMobGFiZWxzLHJvdW5kKGJya3NbaWR4ICsgMV0sIDIpKQogIH0KICBsYWJlbHMgPC0gbGFiZWxzWzE6bGVuZ3RoKGxhYmVscyktMV0KICAjIGRlZmluZSBhIG5ldyB2YXJpYWJsZSBvbiB0aGUgZGF0YSBzZXQganVzdCBhcyBhYm92ZQogIGRhdGEkYnJrcyA8LSBjdXQoZGF0YSR2YXIxLCAKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGJya3MsIAogICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxhYmVscykKICBicmtzX3NjYWxlIDwtIGxldmVscyhkYXRhJGJya3MpCiAgbGFiZWxzX3NjYWxlIDwtIChicmtzX3NjYWxlKQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAKICB1bml2YXJfcGxvdCA8LXBsb3RfdXNtYXAoZGF0YSA9IGRhdGEsIHZhbHVlcyA9ICJicmtzIiwgaW5jbHVkZSA9IGMoIlRYIiksIGNvbG9yID0gImJsYWNrIikgKyAKICAgIHRoZW1lX21hcCgpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgICB2YWx1ZXMgPSBjb2xvdXJzLAogICAgICBuYW1lID0gbGVnZW5kX3RleHQsCiAgICAgIGRyb3AgPSBGQUxTRSwgCiAgICAgIGxhYmVscyA9IGxhYmVsc19zY2FsZSwKICAgICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQoCiAgICAgICAgZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIGtleWhlaWdodCA9IHVuaXQoNiwgdW5pdHMgPSAibW0iKSwKICAgICAgICBrZXl3aWR0aCA9IHVuaXQoMTAwIC8gbGVuZ3RoKGxhYmVscyksIHVuaXRzID0gIm1tIiksCiAgICAgICAgdGl0bGUucG9zaXRpb24gPSAndG9wJywKICAgICAgICB0aXRsZS5oanVzdCA9IDAsCiAgICAgICAgbGFiZWwuaGp1c3QgPSAxLAogICAgICAgIG5yb3cgPSAxLAogICAgICAgIGJ5cm93ID0gVCwKICAgICAgICByZXZlcnNlID0gRiwKICAgICAgICBsYWJlbC5wb3NpdGlvbiA9ICJib3R0b20iKSwKICAgICAgbmEudHJhbnNsYXRlID0gRkFMU0UpICsgCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICsKICAgIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE0KSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJ0b3AiKQogIAogIHJldHVybih1bml2YXJfcGxvdCkKfSAjIEVORCBPRiBGVU5DVElPTiAjIDMKCmV4dHJhY3RfZGF0YWZyYW1lMiA8LSBmdW5jdGlvbihtYXBfZGF0YSwgeWVhcikgewogIAogIGxlZ2VuZF90ZXh0ID0gIlJlbW92YWxzIHBlciAxSyBjaGlsZHJlbiIKICAKICAjIEZpbHRlciBmb3IgQ2hvc2VuIFllYXIKICBtYXBfZGF0YV95ZWFyIDwtIGZpbHRlcihtYXBfZGF0YSwgWWVhciA9PSB5ZWFyKQogIAogICMgQnVpbGRpbmcgdGhlIHBhcnRzIG9mIHRoZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGgKICBtZGF0YSA8LSBtYXBfZGF0YV95ZWFyICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWdpb24iLCAiZmlwcyIsICJsb24iLCAibGF0IikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJFJlbW92YWxzX1RvdGFsX0NvdW50eV9wZXIxSwogIGRhdGEgPC0gY2JpbmQobWRhdGEsdmFyMSkgIAogIAogIGRhdGEkdmFyMVtkYXRhJHZhcjE9PTBdIDwtIE5BIAogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjIENvbXB1dGUgc2NhbGUKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgY29sb3VycyA9IGMoIiNhOWE5YTkiLCIjZWFjMjU5IiwiI2YzOWY2MiIsIiNmNjczMDAiLCIjZTUyODM1IiwiIzgxMDMwMSIpCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDUsIDEwLCAxNSwgMjAsIDMwLCA1MCkKICBmb3IoaWR4IGluIDE6bGVuZ3RoKGJya3MpKXsKICAgIGxhYmVscyA8LSBjKGxhYmVscyxyb3VuZChicmtzW2lkeCArIDFdLCAyKSkKICB9CiAgbGFiZWxzIDwtIGxhYmVsc1sxOmxlbmd0aChsYWJlbHMpLTFdCiAgIyBkZWZpbmUgYSBuZXcgdmFyaWFibGUgb24gdGhlIGRhdGEgc2V0IGp1c3QgYXMgYWJvdmUKICBkYXRhJGJya3MgPC0gY3V0KGRhdGEkdmFyMSwgCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBicmtzLCAKICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsYWJlbHMpCiAgYnJrc19zY2FsZSA8LSBsZXZlbHMoZGF0YSRicmtzKQogIGxhYmVsc19zY2FsZSA8LSAoYnJrc19zY2FsZSkKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgCiAgcmV0dXJuKGRhdGEpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAzYgoKZXh0cmFjdF9wcmlvcml0eV9saXN0MiA8LSBmdW5jdGlvbihtYXBfZGF0YSwgeWVhcikgewogIAogIGNvbG9yX21hcCA9IGMoIiNkYTRmNTgiLCIjZWRhOGE5IiwiI2U4ZTdlNiIsCiAgICAgICAgICAgICAgICAiI2E0NGM1NSIsIiNiMDljYTUiLCIjYTRkNWUxIiwKICAgICAgICAgICAgICAgICIjNWEzZjQ5IiwiIzViN2Q4ZiIsIiM0M2FhYzAiKQogIAogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgVGhlIGJyZWFrczoKICB4X2Jya19wb2ludHMgPSBjKDMsIDUpICAgIyByZW1vdmFscwogIHlfYnJrX3BvaW50cyA9IGMoNiwgMTEpICAjIGhvbWVzCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogICMgQnVpbGRpbmcgdGhlIHBhcnRzIG9mIHRoZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGgKICBtZGF0YSA8LSBtYXBfZGF0YV95ZWFyICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWdpb24iLCAiZmlwcyIsICJsb24iLCAibGF0IikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJFJlbW92YWxzX1RvdGFsX0NvdW50eV9wZXIxSwogIHZhcjIgPSBtYXBfZGF0YV95ZWFyJEhvbWVzX1RvdGFsX0NvdW50eV9wZXIxMDBLCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxLHZhcjIpICAKICAKICB4ID0gYXMubnVtZXJpYyh1bmxpc3QoZGF0YVs3XSkpCiAgeSA9IGFzLm51bWVyaWModW5saXN0KGRhdGFbOF0pKQogIAogICMgY3JlYXRlIDMgYnVja2V0cyBmb3IgdmFyaWFibGUgMQogIHF1YW50aWxlc194IDwtIHF1YW50aWxlKHgsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gYygwLGVjZGYoeCkoeF9icmtfcG9pbnRzWzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNkZih4KSh4X2Jya19wb2ludHNbMl0pLDEpLCBuYS5ybSA9IFRSVUUpCiAgIyBjcmVhdGUgMyBidWNrZXRzIGZvciB2YXJpYWJsZSAyCiAgcXVhbnRpbGVzX3kgPC0gcXVhbnRpbGUoeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBjKDAsZWNkZih5KSh5X2Jya19wb2ludHNbMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2RmKHkpKHlfYnJrX3BvaW50c1syXSksMSksIG5hLnJtID0gVFJVRSkKICAKICAjIGNyZWF0ZSBjb2xvciBzY2FsZSB0aGF0IGVuY29kZXMgdHdvIHZhcmlhYmxlcwogIGJpdmFyaWF0ZV9jb2xvcl9zY2FsZSA8LSB0aWJibGUoCiAgICAiMyAtIDMiID0gY29sb3JfbWFwWzFdLCAjIGhpZ2ggWCwgaGlnaCBZCiAgICAiMiAtIDMiID0gY29sb3JfbWFwWzJdLAogICAgIjEgLSAzIiA9IGNvbG9yX21hcFszXSwgIyBsb3cgWCwgaGlnaCBZCiAgICAiMyAtIDIiID0gY29sb3JfbWFwWzRdLAogICAgIjIgLSAyIiA9IGNvbG9yX21hcFs1XSwgIyBtZWRpdW0gWCwgbWVkaXVtIFkKICAgICIxIC0gMiIgPSBjb2xvcl9tYXBbNl0sCiAgICAiMyAtIDEiID0gY29sb3JfbWFwWzddLCAjIGhpZ2ggWCwgbG93IFkKICAgICIyIC0gMSIgPSBjb2xvcl9tYXBbOF0sCiAgICAiMSAtIDEiID0gY29sb3JfbWFwWzldICMgbG93IFgsIGxvdyBZCiAgKSAlPiUKICAgIGdhdGhlcigiZ3JvdXAiLCAiZmlsbCIpCiAgCiAgIyBjdXQgaW50byBncm91cHMgZGVmaW5lZCBhYm92ZSBhbmQgam9pbiBmaWxsCiAgYmFyIDwtIGRhdGEgJT4lCiAgICBtdXRhdGUoCiAgICAgIHhfcXVhbnRpbGVzID0gY3V0KAogICAgICAgIHgsCiAgICAgICAgYnJlYWtzID0gcXVhbnRpbGVzX3gsCiAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFCiAgICAgICksCiAgICAgIHlfcXVhbnRpbGVzID0gY3V0KAogICAgICAgIHksCiAgICAgICAgYnJlYWtzID0gcXVhbnRpbGVzX3ksCiAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFCiAgICAgICksCiAgICAgIGdyb3VwID0gcGFzdGUoCiAgICAgICAgYXMubnVtZXJpYyh4X3F1YW50aWxlcyksICItIiwKICAgICAgICBhcy5udW1lcmljKHlfcXVhbnRpbGVzKQogICAgICApCiAgICApICU+JQogICAgIyB3ZSBub3cgam9pbiB0aGUgYWN0dWFsIGhleCB2YWx1ZXMgcGVyICJncm91cCIKICAgICMgc28gZWFjaCBjb3VudHkgaGFzIGEgaGV4IHZhbHVlIGJhc2VkIG9uIHggYW5kIHkKICAgIGxlZnRfam9pbihiaXZhcmlhdGVfY29sb3Jfc2NhbGUsIGJ5ID0gImdyb3VwIikKICAKICBmb28gPSBiYXIgJT4lIHNlbGVjdChmaXBzLGZpbGwpCiAgY29sb3VycyA9IGNvbG9yX21hcAogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICB0aGVfbGlzdCA9IHNvcnQoYmFyJENvdW50eVtiYXIkZmlwcyAlaW4lIChmb28kZmlwc1tmb28kZmlsbD09IiM1YTNmNDkiXSldKQogIAogIHJldHVybih0aGVfbGlzdCkKfSAjIEVORCBPRiBGVU5DVElPTiAjIDdiCmV4dHJhY3RfZGF0YWZyYW1lIDwtIGZ1bmN0aW9uKG1hcF9kYXRhLCB5ZWFyKSB7CiAgCiAgY29sb3JfbWFwID0gYygiI2RhNGY1OCIsIiNlZGE4YTkiLCIjZThlN2U2IiwKICAgICAgICAgICAgICAgICIjYTQ0YzU1IiwiI2IwOWNhNSIsIiNhNGQ1ZTEiLAogICAgICAgICAgICAgICAgIiM1YTNmNDkiLCIjNWI3ZDhmIiwiIzQzYWFjMCIpCiAgCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0geWVhcikKICAKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIyBUaGUgYnJlYWtzOgogIHhfYnJrX3BvaW50cyA9IGMoMywgNSkgICAjIHJlbW92YWxzCiAgeV9icmtfcG9pbnRzID0gYyg2LCAxMSkgICMgaG9tZXMKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLCiAgdmFyMiA9IG1hcF9kYXRhX3llYXIkSG9tZXNfVG90YWxfQ291bnR5X3BlcjEwMEsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEsdmFyMikgIAogIAogIHggPSBhcy5udW1lcmljKHVubGlzdChkYXRhWzddKSkKICB5ID0gYXMubnVtZXJpYyh1bmxpc3QoZGF0YVs4XSkpCiAgCiAgIyBjcmVhdGUgMyBidWNrZXRzIGZvciB2YXJpYWJsZSAxCiAgcXVhbnRpbGVzX3ggPC0gcXVhbnRpbGUoeCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBjKDAsZWNkZih4KSh4X2Jya19wb2ludHNbMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2RmKHgpKHhfYnJrX3BvaW50c1syXSksMSksIG5hLnJtID0gVFJVRSkKICAjIGNyZWF0ZSAzIGJ1Y2tldHMgZm9yIHZhcmlhYmxlIDIKICBxdWFudGlsZXNfeSA8LSBxdWFudGlsZSh5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9icyA9IGMoMCxlY2RmKHkpKHlfYnJrX3BvaW50c1sxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjZGYoeSkoeV9icmtfcG9pbnRzWzJdKSwxKSwgbmEucm0gPSBUUlVFKQogIAogICMgY3JlYXRlIGNvbG9yIHNjYWxlIHRoYXQgZW5jb2RlcyB0d28gdmFyaWFibGVzCiAgYml2YXJpYXRlX2NvbG9yX3NjYWxlIDwtIHRpYmJsZSgKICAgICIzIC0gMyIgPSBjb2xvcl9tYXBbMV0sICMgaGlnaCBYLCBoaWdoIFkKICAgICIyIC0gMyIgPSBjb2xvcl9tYXBbMl0sCiAgICAiMSAtIDMiID0gY29sb3JfbWFwWzNdLCAjIGxvdyBYLCBoaWdoIFkKICAgICIzIC0gMiIgPSBjb2xvcl9tYXBbNF0sCiAgICAiMiAtIDIiID0gY29sb3JfbWFwWzVdLCAjIG1lZGl1bSBYLCBtZWRpdW0gWQogICAgIjEgLSAyIiA9IGNvbG9yX21hcFs2XSwKICAgICIzIC0gMSIgPSBjb2xvcl9tYXBbN10sICMgaGlnaCBYLCBsb3cgWQogICAgIjIgLSAxIiA9IGNvbG9yX21hcFs4XSwKICAgICIxIC0gMSIgPSBjb2xvcl9tYXBbOV0gIyBsb3cgWCwgbG93IFkKICApICU+JQogICAgZ2F0aGVyKCJncm91cCIsICJmaWxsIikKICAKICAjIGN1dCBpbnRvIGdyb3VwcyBkZWZpbmVkIGFib3ZlIGFuZCBqb2luIGZpbGwKICBiYXIgPC0gZGF0YSAlPiUKICAgIG11dGF0ZSgKICAgICAgeF9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeCwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeCwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgeV9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeSwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeSwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgZ3JvdXAgPSBwYXN0ZSgKICAgICAgICBhcy5udW1lcmljKHhfcXVhbnRpbGVzKSwgIi0iLAogICAgICAgIGFzLm51bWVyaWMoeV9xdWFudGlsZXMpCiAgICAgICkKICAgICkgJT4lCiAgICAjIHdlIG5vdyBqb2luIHRoZSBhY3R1YWwgaGV4IHZhbHVlcyBwZXIgImdyb3VwIgogICAgIyBzbyBlYWNoIGNvdW50eSBoYXMgYSBoZXggdmFsdWUgYmFzZWQgb24geCBhbmQgeQogICAgbGVmdF9qb2luKGJpdmFyaWF0ZV9jb2xvcl9zY2FsZSwgYnkgPSAiZ3JvdXAiKQogIAogIGZvbyA9IGJhciAlPiUgc2VsZWN0KGZpcHMsZmlsbCkKICBjb2xvdXJzID0gY29sb3JfbWFwCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIHJldHVybihiYXIpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyA3YgpgYGAKCmBgYHtyfQptYXBfZGF0YSRlbXB0eV92ZWMgPSByZXAoTkEsIDI1NCkKcGxvdF91c21hcChkYXRhID0gbWFwX2RhdGEsIHZhbHVlcyA9ICJlbXB0eV92ZWMiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogIHRoZW1lX21hcCgpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgICAgICAgdmFsdWVzID0gIndoaXRlIiwgbmEudmFsdWU9IndoaXRlIikgKwogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmF5IiwgZmlsbCA9ICJncmF5IikpIAoKIyAtLS0tLS0tLS0tLS0tLS0KCmBgYAoKYGBge3J9CgptYXBfZGF0YSA8LSBtYXBfZGF0YSAlPiUgc2VwYXJhdGUoUmVnaW9uLCBjKCJEUmVnX051bSIsICJSZWdpb24iKSwgIi0iKQoKbWFwX2RhdGEkRFJlZ19OdW0gPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobWFwX2RhdGEkRFJlZ19OdW0pKQoKYGBgCgoKCmBgYHtyfQoKICBsZWdlbmRfdGV4dCA9ICIiCgogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IDIwMjEpCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRSZWdfTnVtIiwgImZpcHMiLCAibG9uIiwgImxhdCIpCiAgCiAgIyBjcmVhdGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoIHRvIHBsb3QKICB2YXIxID0gbWFwX2RhdGFfeWVhciREUmVnX051bQogIGRhdGEgPC0gY2JpbmQobWRhdGEsdmFyMSkgIAogIAogIGRhdGEkdmFyMVtkYXRhJHZhcjE9PTBdIDwtIE5BIAogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjIENvbXB1dGUgc2NhbGUKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgY29sb3VycyA9IGMoIiM0MzYzZDgiLCIjYWFmZmMzIiwiIzkxMWViNCIsIiNmYWJlZDQiLCIjYzUwMjc1IiwiIzQyZDRmNCIsIiNmNTgyMzEiLCIjZGNiZWZmIiwiI2ZmZTExOSIsIiMwMDdjN2MiLCIjOThENjQwIiwiI2E5YTlhOSIpCiAgCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksMTAsMTEpCiAgCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHBsb3RfdXNtYXAoZGF0YSA9IGRhdGEsIHZhbHVlcyA9ICJicmtzIiwgaW5jbHVkZSA9IGMoIlRYIiksIGNvbG9yID0gImJsYWNrIikgKyAKICAgIHRoZW1lX21hcCgpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgICB2YWx1ZXMgPSBjb2xvdXJzLAogICAgICBuYW1lID0gbGVnZW5kX3RleHQsCiAgICAgIGRyb3AgPSBGQUxTRSwgCiAgICAgIGxhYmVscyA9IGMoIkx1YmJvY2siLCJBYmlsZW5lIiwiQXJsaW5ndG9uIiwiVHlsZXIiLCJCZWF1bW9udCIsIkhvdXN0b24iLCJBdXN0aW4iLCJTYW4gQW50b25pbyIsIk1pZGxhbmQiLCJFbCBQYXNvIiwiRWRpbmJ1cmciKSwKICAgICAgZ3VpZGUgPSBndWlkZV9sZWdlbmQoCiAgICAgICAgZGlyZWN0aW9uID0gInZlcnRpY2FsIiwKICAgICAgICBrZXloZWlnaHQgPSB1bml0KDYsIHVuaXRzID0gIm1tIiksCiAgICAgICAga2V5d2lkdGggPSB1bml0KDEwMCAvIGxlbmd0aChsYWJlbHMpLCB1bml0cyA9ICJtbSIpLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gJ3RvcCcsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLAogICAgICAgIGxhYmVsLmhqdXN0ID0gMSwKICAgICAgICBucm93ID0gMTIsCiAgICAgICAgYnlyb3cgPSBGLAogICAgICAgIHJldmVyc2UgPSBGLAogICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImxlZnQiKSwKICAgICAgbmEudHJhbnNsYXRlID0gRkFMU0UpICsgCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICsKICAgIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTE0KSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArIAogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpCiAgCgpgYGAKCgoKYGBge3J9CkhvbWVzICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKENvdW50KSkKCkhvbWVzICU+JSBncm91cF9ieShZZWFyLCBUeXBlKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKENvdW50KSkgJT4lIAogICAgICAgICAgICBnZ3Bsb3QoYWVzKHggPSAgWWVhciwgeSA9IFRvdGFsLCBmaWxsID0gVHlwZSkpICsgCiAgICAgICAgICAgIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogICAgICAgICAgICBnZ3RpdGxlKCIiKSArCiAgICAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lPSJZZWFyIiwgbGltaXRzPWMoMjAxMC41LCAyMDIxLjUpLCBicmVha3MgPSBjKDIwMTEsMjAxMiwyMDEzLDIwMTQsMjAxNSwyMDE2LDIwMTcsMjAxOCwyMDE5LDIwMjAsMjAyMSkpICsgCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTIsIGFuZ2xlPTMwKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xNCwgYW5nbGU9MCkpICsgCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogICAgICAgICAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgKwogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsgCiAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiSG9tZSBUeXBlIiwgdmFsdWVzID0gYygiIzYwOTFjMiIsICIjMjFjNWFhIiwgIiMwMDAwMDAiKSkgCmBgYAoKCmBgYHtyfQojIDIwMTEgYmFyIGNoYXJ0Cm1hcF9kYXRhXzIwMTEgPC0gbWFwX2RhdGEgJT4lIGZpbHRlcihZZWFyID09ICIyMDExIikgJT4lIGZpbHRlcihIb21lc19Ub3RhbF9Db3VudHk9PTApIAoKc3VtKG1hcF9kYXRhXzIwMTEkSG9tZXNfVG90YWxfQ291bnR5PT0wKQoKbWFwX2RhdGFfMjAxMSA8LSB3aXRoaW4obWFwX2RhdGFfMjAxMSwgCiAgICAgICAgICAgICAgICAgICBSZWdpb248LSBmYWN0b3IoUmVnaW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9bmFtZXMoc29ydCh0YWJsZShSZWdpb24pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNyZWFzaW5nPUZBTFNFKSkpKQpnZ3Bsb3QobWFwX2RhdGFfMjAxMSwgYWVzKHkgPSBSZWdpb24pKSArCiAgZ2VvbV9iYXIoZmlsbD0iYmxhY2siKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9OSwgYW5nbGU9MCkpICsgbGFicyh5ID0gIlJlZ2lvbiIsIHggPSAiQ291bnR5IENvdW50IikKCiMgMjAyMSBiYXIgY2hhcnQKbWFwX2RhdGFfMjAyMSA8LSBtYXBfZGF0YSU+JSBmaWx0ZXIoWWVhciA9PSAiMjAyMSIpICAlPiUgZmlsdGVyKEhvbWVzX1RvdGFsX0NvdW50eT09MCkgCgpzdW0obWFwX2RhdGFfMjAyMSRIb21lc19Ub3RhbF9Db3VudHk9PTApCgptYXBfZGF0YV8yMDIxIDwtIHdpdGhpbihtYXBfZGF0YV8yMDIxLCAKICAgICAgICAgICAgICAgICAgIFJlZ2lvbjwtIGZhY3RvcihSZWdpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1uYW1lcyhzb3J0KHRhYmxlKFJlZ2lvbiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlYXNpbmc9RkFMU0UpKSkpCmdncGxvdChtYXBfZGF0YV8yMDIxLCBhZXMoeSA9IFJlZ2lvbikpICsKICBnZW9tX2JhcihmaWxsPSJibGFjayIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT05LCBhbmdsZT0wKSkgKyBsYWJzKHkgPSAiRFJlZ19OdW0iLCB4ID0gIkNvdW50eSBDb3VudCIpCgpmaWcwID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDIxKSAKZmlnMCArIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSkgCgojIG1hcHMgZmlndXJlCgpmaWcxID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDExKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmZpZzIgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMjEpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdyaWQuYXJyYW5nZShmaWcxK2dndGl0bGUoIjIwMTEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSksIAogICAgICAgICAgICAgZmlnMitnZ3RpdGxlKCIyMDIxIikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpLCAKICAgICAgICAgICAgIG5yb3cgPSAxKQpgYGAKCgpgYGB7cn0KUmVtb3ZhbHMgJT4lIGdyb3VwX2J5KFllYXIsIFJlbW92YWwuU3RhZ2UpICU+JSBzdW1tYXJpc2UoVG90YWwgPSBzdW0oUmVtb3ZhbHMpKSAlPiUgZ2dwbG90KGFlcyh4ID0gIFllYXIsIHkgPSBUb3RhbCwgZmlsbCA9IFJlbW92YWwuU3RhZ2UpKSArIAogICAgICAgICAgICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xMiwgYW5nbGU9NDUpKSArIAogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsKICAgICAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICArCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgKwogICAgICAgICAgICBnZ3RpdGxlKCIiKSArCiAgICAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lPSJZZWFyIiwgbGltaXRzPWMoMjAxMC41LCAyMDIxLjUpLCBicmVha3MgPSBjKDIwMTEsMjAxMiwyMDEzLDIwMTQsMjAxNSwyMDE2LDIwMTcsMjAxOCwyMDE5LDIwMjAsMjAyMSkpICsKICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJSZW1vdmFsIFN0YWdlIiwgdmFsdWVzID0gYygiIzA1OGFiZCIsIiMxYzMxNTIiKSkKCiMgVHJ5aW5nIHRvIGdldCBwZXJjZW50YWdlcwpUb3RhbHNfYnlZZWFyIDwtIFJlbW92YWxzICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXplKFRvdGFsX1llYXIgPSBzdW0oUmVtb3ZhbHMpKSAKVG90YWxzX2J5U3RhZ2VfYnlZZWFyIDwtIFJlbW92YWxzICU+JSBncm91cF9ieShZZWFyLCBSZW1vdmFsLlN0YWdlKSAlPiUgc3VtbWFyaXplKFRvdGFsX1N0YWdlID0gc3VtKFJlbW92YWxzKSkgCnggPC0gbWVyZ2UoVG90YWxzX2J5U3RhZ2VfYnlZZWFyLFRvdGFsc19ieVllYXIsIGJ5ID0gIlllYXIiKSAKeCA8LSBtdXRhdGUoeCwgUGVyY2VudCA9IChUb3RhbF9TdGFnZS9Ub3RhbF9ZZWFyKSoxMDApCnggJT4lIGdncGxvdChhZXMoeCA9ICBZZWFyLCB5ID0gUGVyY2VudCwgZmlsbCA9IFJlbW92YWwuU3RhZ2UpKSArIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9OSwgYW5nbGU9NDUpKSArIGdndGl0bGUoIiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZT0iWWVhciIsIGxpbWl0cz1jKDIwMTAuNSwgMjAyMS41KSwgYnJlYWtzID0gYygyMDExLDIwMTIsMjAxMywyMDE0LDIwMTUsMjAxNiwyMDE3LDIwMTgsMjAxOSwyMDIwLDIwMjEpKSArIAogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICIjYzlkYWY4IiwgZmlsbCA9ICIjYzlkYWY4IikpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzA1OGFiZCIsIiMxYzMxNTIiKSkKCmBgYAoKCmBgYHtyfQpSZW1vdmFscyAlPiUgZ3JvdXBfYnkoWWVhcikgJT4lIHN1bW1hcmlzZShUb3RhbCA9IHN1bShSZW1vdmFscykpIApgYGAKCmBgYHtyfQojIDIwMjEgYmFyIGNoYXJ0CnJlbW92YWxzX2RhdGFfMjAyMSA8LSBleHRyYWN0X2RhdGFmcmFtZTIobWFwX2RhdGEsIDIwMjEpCgojIiNlYWMyNTkiLCIjZjM5ZjYyIiwiI2Y2NzMwMCIKcmVtb3ZhbHNfZGF0YV8yMDIxX2hpZ2ggPC0gZmlsdGVyKHJlbW92YWxzX2RhdGFfMjAyMSAsIGJya3MhPSI1IikgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAiUmVnaW9uIiwiYnJrcyIpCgpyZW1vdmFsc19kYXRhXzIwMjFfaGlnaCA8LSB3aXRoaW4ocmVtb3ZhbHNfZGF0YV8yMDIxX2hpZ2gsIAogICAgICAgICAgICAgICAgICAgUmVnaW9uPC0gZmFjdG9yKFJlZ2lvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPW5hbWVzKHNvcnQodGFibGUoUmVnaW9uKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjcmVhc2luZz1GQUxTRSkpKSkKZ2dwbG90KHJlbW92YWxzX2RhdGFfMjAyMV9oaWdoLCBhZXMoeSA9IFJlZ2lvbikpICsKICBnZW9tX2JhcihmaWxsPSJibGFjayIpICsgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT05LCBhbmdsZT0wKSkgKyBsYWJzKHkgPSAiUmVnaW9uIiwgeCA9ICJDb3VudHkgQ291bnQiKQoKIyAtLS0tLS0tCmxpYnJhcnkoZ2d0ZXh0KSAKbXlfY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6IzAwMDAwMCc+MjAxMTwvc3Bhbj4gIDxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDEzICAyMDE1ICAyMDE3ICAyMDE5ICAyMDIxPC9zcGFuPiIKCmZpZyA9IGNyZWF0ZV9yZW1vdmFsc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAyMSkgCmZpZyArIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSkgCgojIy0tLS0tLS0tLS0tLS0tLS0tCmZpZzMgPSBjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTEpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKZmlnNCA9IGNyZWF0ZV9yZW1vdmFsc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAyMSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKZ3JpZC5hcnJhbmdlKGZpZzMrZ2d0aXRsZSgiMjAxMSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSwgCiAgICAgICAgICAgICBmaWc0K2dndGl0bGUoIjIwMjEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSksIAogICAgICAgICAgICAgbnJvdyA9IDEpCmBgYAoKCmBgYHtyfQojIEJ1aWxkaW5nIHRoZSBwYXJ0cyBvZiB0aGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoCm1kYXRhIDwtIG1hcF9kYXRhICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhvbWVzX1RvdGFsX0NvdW50eV9wZXIxMDBLIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLIikKCm1kYXRhJFllYXI8LWFzLmZhY3RvcihtZGF0YSRZZWFyKQoKbmV3MSA8LW1kYXRhICU+JSBncm91cF9ieShDb3VudHkpICU+JSBzdW1tYXJpc2UoTWVhbkhvbWVzID0gbWVhbihIb21lc19Ub3RhbF9Db3VudHlfcGVyMTAwSykpICU+JSBzZWxlY3QoIk1lYW5Ib21lcyIpIAoKbmV3MiA8LW1kYXRhICU+JSBncm91cF9ieShDb3VudHkpICU+JSBzdW1tYXJpc2UoTWVhblJlbW92YWxzID0gbWVhbihSZW1vdmFsc19Ub3RhbF9Db3VudHlfcGVyMUspKSAlPiUgc2VsZWN0KCJNZWFuUmVtb3ZhbHMiKQoKbmV3MSRNZWFuSG9tZXNbbmV3MSRNZWFuSG9tZXM9PTBdIDwtIE5BIApuZXcyJE1lYW5SZW1vdmFsc1tuZXcyJE1lYW5SZW1vdmFscz09MF0gPC0gTkEgCgojIFBsb3QgMQpsYXlvdXQobWF0ID0gbWF0cml4KGMoMSwyKSwyLDEsIGJ5cm93PVRSVUUpLCAgaGVpZ2h0ID0gYygxLDgpKQpwYXIobWFyPWMoMCwgMy4xLCAxLjEsIDIuMSkpCmJveHBsb3QobmV3MSRNZWFuSG9tZXMsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygwLDUwKSwgeGF4dD0ibiIgLCBjb2w9cmdiKDMvMjU1LDE0OS8yNTUsMTE0LzI1NSwwLjg1KSAsIGZyYW1lPUYpCnBhcihtYXI9Yyg0LCAzLjEsIDEuMSwgMi4xKSkKaGlzdChuZXcxJE1lYW5Ib21lcywgYnJlYWtzPTQwICwgY29sPXJnYigwLzI1NSwwLzI1NSwxMjQvMjU1LDAuODUpICwgYm9yZGVyPVQgLCBtYWluPSIiICwgeGxhYj0iQXZlcmFnZSBOdW1iZXIgb2YgSG9tZXMgUGVyIDEwMEsgUmVzaWRlbnRzIGJldHdlZW4gMjAxMS0yMDIxIiwgeGxpbT1jKDAsNTApKQoKIyBQbG90IDIKbGF5b3V0KG1hdCA9IG1hdHJpeChjKDEsMiksMiwxLCBieXJvdz1UUlVFKSwgIGhlaWdodCA9IGMoMSw4KSkKcGFyKG1hcj1jKDAsIDMuMSwgMS4xLCAyLjEpKQpib3hwbG90KG5ldzIkTWVhblJlbW92YWxzLCBob3Jpem9udGFsPVRSVUUgLCB5bGltPWMoMCwxNSksIHhheHQ9Im4iICwgY29sPXJnYigzLzI1NSwxNDkvMjU1LDExNC8yNTUsMC44NSkgLCBmcmFtZT1GKSArIGdlb21faGxpbmUoeGludGVyY2VwdD0xMCkgCnBhcihtYXI9Yyg0LCAzLjEsIDEuMSwgMi4xKSkKaGlzdChuZXcyJE1lYW5SZW1vdmFscywgYnJlYWtzPTQwICwgY29sPXJnYigwLzI1NSwwLzI1NSwxMjQvMjU1LDAuODUpICwgYm9yZGVyPVQgLCBtYWluPSIiICwgeGxhYj0iQXZlcmFnZSBOdW1iZXIgb2YgUmVtb3ZhbHMgUGVyIDFLIENoaWxkcmVuIGJldHdlZW4gMjAxMS0yMDIxIiwgeGxpbT1jKDAsMTUpKSAKCnF1YW50aWxlKG5ldzEkTWVhbkhvbWVzLHByb2JzID0gMC4zMzMzMyxuYS5ybSA9IFRSVUUpCnF1YW50aWxlKG5ldzEkTWVhbkhvbWVzLHByb2JzID0gMC42NjY2NyxuYS5ybSA9IFRSVUUpCgpxdWFudGlsZShuZXcyJE1lYW5SZW1vdmFscyxwcm9icyA9IDAuMzMzMzMsbmEucm0gPSBUUlVFKQpxdWFudGlsZShuZXcyJE1lYW5SZW1vdmFscyxwcm9icyA9IDAuNjY2NjcsbmEucm0gPSBUUlVFKQpgYGAKCgoKYGBge3J9CiMgTWFwIEZ1bmN0aW9uIHdpdGggMyBCcmVha3MKY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlXzNicmtzIDwtIGZ1bmN0aW9uKG1hcF9kYXRhLCB5ZWFyKSB7CiAgCiAgbGVnZW5kX3RleHQgPSAiRkFEIEhvbWVzIHBlciAxMDBLIHJlc2lkZW50cyIKICAKICAjIEZpbHRlciBmb3IgQ2hvc2VuIFllYXIKICBtYXBfZGF0YV95ZWFyIDwtIGZpbHRlcihtYXBfZGF0YSwgWWVhciA9PSB5ZWFyKQogIAogICMgQnVpbGRpbmcgdGhlIHBhcnRzIG9mIHRoZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGgKICBtZGF0YSA8LSBtYXBfZGF0YV95ZWFyICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWdpb24iLCAiZmlwcyIsICJsb24iLCAibGF0IikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJEhvbWVzX1RvdGFsX0NvdW50eV9wZXIxMDBLCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxKSAgCiAgCiAgI2RhdGEkdmFyMVtkYXRhJHZhcjE9PTBdIDwtIE5BIAogIAogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjIENvbXB1dGUgc2NhbGUKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgY29sb3VycyA9IGMoIiM0M2FhYmYiLCIjYTRkNWUxIiwiIzk2OTY5NiIpCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDYsMTEsNTApCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCg2NSAvIGxlbmd0aChsYWJlbHMpLCB1bml0cyA9ICJtbSIpLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gJ3RvcCcsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLAogICAgICAgIGxhYmVsLmhqdXN0ID0gMSwKICAgICAgICBucm93ID0gMSwKICAgICAgICBieXJvdyA9IFQsCiAgICAgICAgcmV2ZXJzZSA9IEYsCiAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIiksIAogICAgICAgIG5hLnRyYW5zbGF0ZSA9IEZBTFNFKSArIAogICAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArCiAgICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsgCiAgICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikgICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgCiAgcmV0dXJuKHVuaXZhcl9wbG90KQp9ICMgRU5EIE9GIEZVTkNUSU9OICMgMiB1cGRhdGVkCgpjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGVfM2Jya3MgPC0gZnVuY3Rpb24obWFwX2RhdGEsIHllYXIpIHsKICAKICBsZWdlbmRfdGV4dCA9ICJSZW1vdmFscyBwZXIgMUsgY2hpbGRyZW4iCiAgCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0geWVhcikKICAKICAjIEJ1aWxkaW5nIHRoZSBwYXJ0cyBvZiB0aGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoCiAgbWRhdGEgPC0gbWFwX2RhdGFfeWVhciAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiwgImZpcHMiLCAibG9uIiwgImxhdCIpCiAgCiAgIyBjcmVhdGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoIHRvIHBsb3QKICB2YXIxID0gbWFwX2RhdGFfeWVhciRSZW1vdmFsc19Ub3RhbF9Db3VudHlfcGVyMUsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEpICAKICAKICAjZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBjb2xvdXJzID0gYygiIzk2OTY5NiIsIiNlZGE4YTkiLCIjY2YzOTQ2IikKICBsYWJlbHMgPC0gYygpCiAgYnJrcyA8LSBjKDAsMywgNSwgNTApCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCg2NSAvIGxlbmd0aChsYWJlbHMpLCB1bml0cyA9ICJtbSIpLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gJ3RvcCcsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLAogICAgICAgIGxhYmVsLmhqdXN0ID0gMSwKICAgICAgICBucm93ID0gMSwKICAgICAgICBieXJvdyA9IFQsCiAgICAgICAgcmV2ZXJzZSA9IEYsCiAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIiksCiAgICAgIG5hLnRyYW5zbGF0ZSA9IEZBTFNFKSArIAogICAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArCiAgICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsgCiAgICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAKICByZXR1cm4odW5pdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAzIHVwZGF0ZWQKYGBgCgoKCmBgYHtyfQpmaWdfaG9tZXMgPC0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlXzNicmtzKG1hcF9kYXRhLCAyMDIxKQoKZmlnX3JlbW92YWxzIDwtIGNyZWF0ZV9yZW1vdmFsc19wbG90X3NpbXBsZV8zYnJrcyhtYXBfZGF0YSwgMjAyMSkKCgpncmlkLmFycmFuZ2UoZmlnX2hvbWVzK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSxmaWdfcmVtb3ZhbHMrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpLCAKICAgICAgICAgICAgIG5yb3cgPSAxKSAKYGBgCgoKCgoKYGBge3J9CmNyZWF0ZV9ob21lc19yZW1vdmFsc19wbG90KG1hcF9kYXRhLCAyMDIxKQoKdGhlX2xpc3QgPC0gZXh0cmFjdF9wcmlvcml0eV9saXN0MihtYXBfZGF0YSwgMjAyMSkKdGhlX2xpc3QgCgpiYXIgPC0gZXh0cmFjdF9kYXRhZnJhbWUobWFwX2RhdGEsIDIwMjEpCgpoaWdoX25lZWRfZGYgPC0gZmlsdGVyKGJhciwgZmlsbD09IiM1YTNmNDkiKSAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIikKCnRhYmxlKGhpZ2hfbmVlZF9kZiRSZWdpb24pCgpoaWdoX25lZWRfZGYgPC0gd2l0aGluKGhpZ2hfbmVlZF9kZiwgCiAgICAgICAgICAgICAgICAgICBSZWdpb248LSBmYWN0b3IoUmVnaW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9bmFtZXMoc29ydCh0YWJsZShSZWdpb24pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNyZWFzaW5nPUZBTFNFKSkpKQpnZ3Bsb3QoaGlnaF9uZWVkX2RmLCBhZXMoeSA9IFJlZ2lvbikpICsKICBnZW9tX2JhcihmaWxsPSIjNWEzZjQ5IikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyBsYWJzKHkgPSAiVGV4YXMgUmVnaW9uIiwgeCA9ICJIaWdoLW5lZWQgQ291bnR5IENvdW50IikgKyB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpIAoKCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2d0ZXh0KSAKCm15X2NhcHRpb24gPSAiPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTE8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxMyAgMjAxNSAgMjAxNyAgMjAxOSAgMjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTYpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpIAoKYGBgCmBgYHtyfQpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExPC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTM8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxNSAgMjAxNyAgMjAxOSAgMjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTMpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpIApgYGAKCmBgYHtyfQpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzPC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTU8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxNyAgMjAxOSAgMjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTUpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpIApgYGAKCmBgYHtyfQpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzICAyMDE1PC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTc8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxOSAgMjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTcpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ2d0ZXh0KSAKCm15X2NhcHRpb24gPSAiPHNwYW4gc3R5bGU9J2NvbG9yOiNlY2VjZWMnPjIwMTEgIDIwMTMgIDIwMTUgIDIwMTc8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6IzAwMDAwMCc+MjAxOTwvc3Bhbj4gIDxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDIxPC9zcGFuPiIKCmZpZyA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAxOSkKZmlnICsgCiAgbGFicyhjYXB0aW9uPW15X2NhcHRpb24pICsgCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuMTUsIHNpemU9cmVsKDEuMjIpKSkgKwogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4xLCBzaXplPTIwLCBmYWNlPSJib2xkIiksIAogICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikKICApICsgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzICAyMDE1ICAyMDE3ICAyMDE5PC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMjE8L3NwYW4+IgoKZmlnID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDIxKSAKZmlnICsgCiAgbGFicyhjYXB0aW9uPW15X2NhcHRpb24pICsgCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuMTUsIHNpemU9cmVsKDEuMjIpKSkgKwogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4xLCBzaXplPTIwLCBmYWNlPSJib2xkIiksIAogICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikKICApICsgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKSAKYGBgCgoKCgoKCgo=